#include"mystdio.h"
#include<sys/types.h>//pid
#include<fcntl.h>//O_WEONLY
#include<sys/stat.h>//定义结构体状态
#include<string.h>//memcpy,strcmp
#include<stdlib.h>//malloc,free
#include<unistd.h>//系统函数open, close write

//静态函数，初始化MyFile结构体
//参数：文件描述符fd， 打开模式flag
static MyFile* BuyFile(int fd, int flag)
{
	MyFile* f = (MyFile*)malloc(sizeof(MyFile));
	if (f == NULL) return NULL;

	//初始化成员
	f->_bufferlen = 0;
	f->_fileno = fd;
	f->_flag = flag;
	f->_flush_method = LINE_FLUSH;//默认行刷新
	//清空输出缓冲区
	memset(f->_outbuffer, 0, sizeof(f->_outbuffer));
	return f;
}

//函数声明
//1代开文件，返回文件指针
MyFile* MyFopen(const char* path, const char* mode)
{
	int fd = -1;
	int flag = 0;
	//根据mode字符串设置flag和打开文件
	if (strcmp(mode, "w") == 0)
	{
		flag = O_CREAT | O_WRONLY | O_TRUNC;// 打开文件：路径path，标志flag，权限0666（所有者、组、其他都可读写）
		fd = open(path, flag, 0666);
	}
	else if (strcmp(mode, "a") == 0)
	{
		flag = O_CREAT | O_WRONLY | O_APPEND;// 追加模式：创建、只写、追加（在文件末尾写）
		fd = open(path, flag, 0666);
	}
	else if (strcmp(mode, "r") == 0)// 读模式：可读可写（此处简化为RDWR，实际应是O_RDONLY）
	{
		flag = O_RDWR;
		fd = open(path, flag, 0666);
	}
	else
	{
		// TODO：处理不支持的模式（如返回NULL）
	}
	return BuyFile(fd, flag);
}
//2关闭文件
// 实现MyFclose：关闭文件（模拟fclose）
// 参数：MyFile指针file（要关闭的文件）
void Myclose(MyFile* file)
{
	//防御性判断，无效文件
	if (file == NULL || file->_fileno < 0)return ;
	//关闭前先刷新，确保写入
	MyFFlush(file);
	//关闭文件描述符，释放内核资源
	close(file->_fileno);
	//释放结构体资源
	free(file);
}
//3项文件写入（带缓冲）
// 实现MyFwrite：写入数据（带缓冲，模拟fwrite）
// 参数：file-文件指针，str-要写入的数据，len-数据长度
// 返回：0（简化处理，实际可返回写入的字节数）
int Mywrite(MyFile* file, void* str, int len)
{
	//1将数据拷贝到用户语言级缓冲区outbuffer
	//从缓冲区当前末尾bufferlen位置开始拷贝，长度为len
	memcpy(file->_outbuffer + file->_bufferlen, str, len);
	//更新长度
	file->_bufferlen += len;

	//2判断是否要刷新缓冲区，若行刷新且最后一个字符是"\n"
	if ((file->_flush_method & LINE_FLUSH) && file->_outbuffer[file->_bufferlen - 1] == '\n')
	{
		MyFFlush(file);
	}
	return 0;
}
//4刷新缓冲区，写入内核
void MyFFlush(MyFile* file)
{
	// 缓冲区为空，无需刷新，直接返回
	if (file->_bufferlen <= 0) return;

	// 将用户态缓冲区的数据写入内核（通过系统调用write）
   // 写入长度为bufferlen，返回实际写入的字节数（此处忽略错误处理）
	int n = write(file->_fileno, file->_outbuffer, file->_bufferlen);
	(void)n;// 消除未使用变量的警告

    // 强制刷新内核缓冲区到磁盘（确保数据真正写入文件，而非停留在内核缓存）
	//fsync(file->_fileno);

	// 清空缓冲区（已写入内核，用户态缓冲区可复用）
	file->_bufferlen = 0;
}




